home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1997 August
/
Macworld (1997-08).dmg
/
Shareware World
/
Info
/
For Developers
/
InstallerMaker™ 4.0 Installer
/
Customizing InstallerMaker
/
Sample Code
/
Utilities
/
IMPackages256.c
next >
Wrap
Text File
|
1995-08-03
|
10KB
|
342 lines
/******************************************************************************
**
** Project Name: InstallerMaker 3.0 Demo Code
** File Name: IMPackages256.c
**
** Description: These are useful routines for manipulating the IM 3.0 package
** bit strings.
**
** Packages field
** ==============
**
** The interpretation of packages for the code rsrcs is:
**
** IM 2.0: packages should be interpreted as a 16 bit field.
** Bit 0 is the lowest bit.
**
** IM 3.0: packages should be interpreted as a 128 bit field.
** packages[0] contains bits 0-31 where 0 is the lowest bit.
** packages[1] contains bits 32-63 where 32 is the lowest bit.
** Similarly for packages[2] and packages[3].
**
** packages is a bit mask where bit 0 set means std pkg, bit 1
** set means pkg A, bit 2 means B, etc. For compatibility, a
** value of zero is synonymous with all ones.
**
** The packages field typically specifies the currently selected
** pkgs unless otherwise noted.
**
**
** Copyright© 1994-1995 Aladdin Systems, inc.
**
*******************************************************************************
** L E G A L N I C E T I E S
*******************************************************************************
This source code is (c) 1995 Aladdin Systems, Inc. You are free to use it
in connection with your own products and distribute it in either source code
or object code form. However, this source code and accompanying written
materials (including instructions for use) are provided "as is" without
warranty of any kind. Further, Aladdin Systems does not warrant, or make
representations regarding the use, or the results of the use, of the source
code or written materials in terms of correctness, accuracy, reliability,
currentness, or otherwise. No oral or written information or advice given
by Aladdin Systems or its employees shall create a warranty, and you may not
rely on such information or advice.
Neither Aladdin Systems nor anyone else who has been involved with the
creation, production, or delivery of the source code shall be liable for
any direct, indirect, consequential, or incidental damages (including damages
for loss of business profits, business interruption, loss of business
information, and the like) arising out of the use or the inability to use the
source code even if Aladdin Systems has been advised of the possibility of
such damages. Because some states do not allow the exclusion or limitation
of liability for consequential or incidental damages or the limitations of
duration of implied warranty, the above limitations may not apply to you.
*******************************************************************************
** A U T H O R I D E N T I T Y
*******************************************************************************
**
** Initials Name
** -------- -----------------------------------------------
** RMT Robert Thorne
**
*******************************************************************************
** R E V I S I O N H I S T O R Y
*******************************************************************************
**
** Date Time Author Description
** -------- ----- ------ ---------------------------------------------
** 1/2/95 RMT Pulled from test code for new file
**
******************************************************************************/
#include "IMPackages256.h"
// Utility routines to do fast string manipulations
static void TransToUpperCase ( StringPtr str ) ;
static char *CopyAsCStr ( StringPtr pStr, char *cStr ) ;
//Defines for quick translation of characters
#define NumToLetter( num ) ((num) + 'A' - 1 )
#define kLowerToUpper ('a' - 'A' )
#define kMaxCodeLen 4
// Converts a string in place to uppercase
void TransToUpperCase ( StringPtr str )
{
register StringPtr sPtr = str, lim = str + str[0] + 1;
char c ;
if ( sPtr )
{
sPtr++ ; // pass on the length bit
while ( sPtr < lim )
{
c = *sPtr ;
if ( 'a' <= c && c <= 'z' )
*sPtr -= kLowerToUpper ; // 'a' > 'A' in ASCII
sPtr++ ;
}
}
}
// Copies a Pascal string from pStr to the C string cStr, converting it
// in the same operation.
static char *CopyAsCStr ( StringPtr pStr, char *cStr )
{
short len = pStr [0] , index ;
unsigned char *cPtr = (unsigned char *) cStr ; // We don't want the compiler
// mangling 8-bit codes
*cPtr = 0 ; // In case we have a null string
if (len)
{
for (index = 1; index <= len ; index++, cPtr++ )
*cPtr = pStr [index] ;
*cPtr = 0 ;
}
return cStr ;
}
//**** PUBLIC INTERFACE STARTS HERE...
//*** GetPackageNumber ***
// Valid formats are "Std" for "Standard Package", "A"..."Z", and "AA".."DW".
// Pass these as Pascal strings. This routine is case-insensitive.
short GetPackageNumber ( StringPtr pkgStr )
{
short len = pkgStr[0] ;
short rslt = -1 ; // for "Not a package"
char c ;
TransToUpperCase (pkgStr) ;
switch (len)
{
case 1: // A-Z
c = pkgStr[1] ;
if ( 'A'<= c && c <= 'Z' )
rslt = c - 'A' + 1 ;
break ;
case 2: // AA - DV
c = pkgStr[1] ;
if ( 'A' <= c && c <= 'D' )
{
rslt = (c - 'A' + 1) * 26 ;
c = pkgStr [2] ;
if ( 'A'<= c && c <= 'Z' )
rslt += c - 'A' + 1 ;
else
rslt = -1 ;
}
break ;
case 3: // The standard package; "\pSTD" is the only valid combo
if ( pkgStr[1] == 'S' &&
pkgStr[2] == 'T' &&
pkgStr[3] == 'D' ) rslt = 0 ;
break ;
}
return rslt < 128 ? rslt : -1 ; // Make sure the number is actually valid
}
//*** GetPkgLetters ***
// Passes back a string that represents that package number. Currently, the
// largest string this passes back is 4 bytes (for "Std"), but allocate a little
// more for safety.
char *GetPkgLetters ( short pkgCode, char *smallStr )
{
// Currently, longest string is 3 letters. May change.
short lowPart, highPart ;
char *cPtr = smallStr ;
if ( pkgCode > 0 && pkgCode < 128 ) // a letter code
{
highPart = pkgCode/26 ;
lowPart = pkgCode - highPart*26 ;
if ( highPart > 0 )
{
*cPtr = NumToLetter( highPart ) ;
cPtr++ ;
}
*cPtr = NumToLetter( lowPart ) ;
cPtr++ ;
*cPtr = 0 ; // Final null to close string.
}
else if ( pkgCode == 0 ) // Std package
{
*cPtr = 'S' ; cPtr++ ;
*cPtr = 't' ; cPtr++ ;
*cPtr = 'd' ; cPtr++ ;
*cPtr = 0 ;
}
else // Bad value
{
*cPtr = '\?' ; cPtr++ ;
*cPtr = 0 ;
}
return smallStr ;
}
//*** GetPackageBit ***
// Checks if bit # bitNo is set in the packages array. This passes back
// 0 if not set, 1 if set, and -1 for an illegal bitNo.
short GetPackageBit ( unsigned long *packages, short bitNo )
{
// return 0 or 1 for good; -1 for a bad number
short rslt , group, offset ;
if ( bitNo < 128 && bitNo >= 0 ) // valid
{
group = bitNo / 32 ; // which long?
offset = bitNo - group * 32 ; // which bit within the group?
rslt = ((1L << offset ) & packages [group]) != 0 ;
}
else
rslt = -1 ;
return rslt ;
}
//*** SetPackageBit ***
// Turns on or turns off bit bitNo.
void SetPackageBit ( unsigned long *packages, short bitNo, Boolean turnOn )
{
// We set the bit we want if it's in the valid range; otherwise, we do nothing
short group, offset ;
if ( bitNo < 128 && bitNo >= 0 ) // valid
{
group = bitNo / 32 ; // which long?
offset = bitNo - group * 32 ; // which bit within the group?
if ( turnOn )
packages [group] |= (1L << offset ) ;
else
packages [group] &= ~(1L << offset ) ;
}
}
//*** ConstructPkgString ***
// Returns a comma-delimited string listing the package bits set. Note that
// this list can get rather long: an average of 3 chars per set bit means you
// can require up to 360 bytes if all bits are set.
// Note: safer if I took a length argument and stopped adding bits.
char *ConstructPkgString ( unsigned long *packages, char *store, short storeLen )
{
// Be careful to have enough store for this routine, since on average
// each bit set will require 3 bytes. 512 is probably safe.
short i = 0 , j = 0 , group = 0, offset = 0 ;
char oneCode [10] ;
char lastTerminator = 0 ; // a comma, an elipsis, or nothing
char *endOfStr = store , *cPtr ;
char *rightMargin = store + storeLen - 1 ; // This points to the last possible byte
long thisLong ;
Boolean outtaSpace = true ;
// Terminate our storage if safe to do so
if ( store && storeLen > 0 )
{
store [0] = 0 ;
// Confirm we have enough space to do anything
outtaSpace = ( storeLen < kMaxCodeLen + 1) ;
}
while ( !outtaSpace && i < 4 ) // step down each of the longs in the array
{
if (thisLong = packages[i]) // assignment intended
{
j = 0 ; // initialize this run through the loop
while ( !outtaSpace && j < 32 )
{
// Test each of the bits and print if need be
if ((1L << j) & thisLong)
{
(void) GetPkgLetters ( j + i*32, oneCode ) ; // get the letters
cPtr = oneCode ;
while ( *cPtr ) // let's walk to the end of the string and copy
*endOfStr++ = *cPtr++ ;
// Do we have room for another?
if ( endOfStr + kMaxCodeLen > rightMargin )
{
outtaSpace = true ;
*endOfStr++ = lastTerminator = '…' ; // copy over an elipsis
}
*endOfStr++ = lastTerminator = ',' ; // copy over a comma
}
j++ ; // Next bit in this group
}
}
i++ ; // Next 32 bits
}
// Remove a trailing comma if it's there...
if ( lastTerminator == ',' )
endOfStr-- ;
if ( store )
*endOfStr = 0 ; // Terminate with a null
return store ;
}